// Function.prototype.bind = function(scope, ...args){
//     var fn = this;
//     return function(...args2){
//         return fn.apply(scope, args.concat(args2));
//     };
// };

// Function.prototype.bind = function(scope){
//     var fn = this;
//     var args = [].slice.call(arguments);
//     args.shift();
//     return function(){
//         return fn.apply(scope, args.concat([].slice.call(arguments)));
//     };
// };

function Foo(age, sex, options) {
    console.log(this.name);
    console.log(age);
    console.log(sex);
    console.log(options)
    return 'abcdefg'
}

// var nf = Foo.bind({name: 'abc'});
// nf(18);

// var nf2 = Foo.bind({name: 'abc'}, 22);
// nf2();


// Function.prototype.call = function(scope, ...args){
//     var fn = this;
//     return fn.bind(scope)(...args);
// };

Function.prototype.call2 = function (scope) {
    scope = scope || window;
    var args = [];
    for (var i = 1; i < arguments.length; i++) {
        var arg = arguments[i];
        if (typeof arg === 'string') {
            args.push('"' + arg + '"');
        } else if (typeof arg === 'object') {
            scope['arg' + i] = arg;
            args.push('scope["arg' + i + '"]');
        } else {
            args.push(arg);
        }
    }

    scope.fn = this;
    var res = eval('scope.fn(' + args.join(',') + ')');
    delete scope.fn;
    for (var key in scope) {
        if (key.startsWith('arg')) {
            delete scope[key];
        }
    }
    return res;
};

var res = Foo.call2({ name: 'def' }, 45, 'man', { email: 'ss' });
console.log(res);